#include "Core.h"
#include <cassert>


__BEGIN_NAMESPACE


extern int                  sTagStackIndex;
extern int                  sMemoryTagStack[MAX_MTAG_STACK];
extern size_t               sMemoryStatistic[MAX_TAGS];
extern const char*          sAllocMemoryFile;
extern INT                  sAllocMemoryLine;
extern struct MemAllocInfo* pMemAllocHead;

void* Malloc( size_t size )
{
	struct MemAllocInfo* Ptr = NULL;

	if( 0==size )
		size = 1;

	Ptr = (struct MemAllocInfo*)malloc( sizeof(struct MemAllocInfo) + size );
	if( Ptr )
	{
		size_t FileNameLength = strlen(sAllocMemoryFile)+1;
		Ptr->TagID = sMemoryTagStack[sTagStackIndex];
		sMemoryStatistic[Ptr->TagID] += sizeof(char)*FileNameLength;
		Ptr->Filename = sAllocMemoryFile;
		sAllocMemoryFile = "";
		Ptr->FileLine = sAllocMemoryLine;
		sAllocMemoryLine = -1;
		Ptr->Size = size;
		Ptr->pNext = NULL;
		Ptr->pPre =  NULL;
		sMemoryStatistic[Ptr->TagID] += sizeof(struct MemAllocInfo) + size;

		if( pMemAllocHead ) {
			pMemAllocHead->pPre = Ptr;
			Ptr->pNext = pMemAllocHead;
		}
		pMemAllocHead = Ptr;
	}
	return (void*)(Ptr+1);
}

void Free( void* buf )
{
	struct MemAllocInfo* Ptr = NULL;
	assert( buf );
	Ptr = (struct MemAllocInfo*)buf - 1;
	assert( Ptr->Size>0 );

	if( Ptr->pPre )
		Ptr->pPre->pNext = Ptr->pNext;
	else
		pMemAllocHead = Ptr->pNext;

	if( Ptr->pNext )
		Ptr->pNext->pPre = Ptr->pPre;

	sMemoryStatistic[Ptr->TagID] -= (UINT32)Ptr->Size;
	free(Ptr);
}

void* AlignMalloc( size_t size, size_t align )
{
	struct MemAllocInfo* Ptr = NULL;

	if( 0==size )
		size = 1;
#if( PLATFORM==PLATFORM_WINDOWS )
	Ptr = (struct MemAllocInfo*)_aligned_malloc( sizeof(struct MemAllocInfo) + size, align );
#else
#error Need define align alloc function
#endif
	if( Ptr )
	{
		size_t FileNameLength = strlen(sAllocMemoryFile)+1;
		Ptr->TagID = sMemoryTagStack[sTagStackIndex];
		sMemoryStatistic[Ptr->TagID] += sizeof(char)*FileNameLength;
		Ptr->Filename = sAllocMemoryFile;
		sAllocMemoryFile = "";
		Ptr->FileLine = sAllocMemoryLine;
		sAllocMemoryLine = -1;
		Ptr->Size = size;
		Ptr->pNext = NULL;
		Ptr->pPre =  NULL;
		sMemoryStatistic[Ptr->TagID] += sizeof(struct MemAllocInfo) + size;

		if( pMemAllocHead ) {
			pMemAllocHead->pPre = Ptr;
			Ptr->pNext = pMemAllocHead;
		}
		pMemAllocHead = Ptr;
	}
	return (void*)(Ptr+1);
}

void AlignFree( void* buf )
{
	struct MemAllocInfo* Ptr = NULL;
	assert( buf );
	Ptr = (struct MemAllocInfo*)buf - 1;
	assert( Ptr->Size>0 );

	if( Ptr->pPre )
		Ptr->pPre->pNext = Ptr->pNext;
	else
		pMemAllocHead = Ptr->pNext;

	if( Ptr->pNext )
		Ptr->pNext->pPre = Ptr->pPre;

	sMemoryStatistic[Ptr->TagID] -= (UINT32)Ptr->Size;
#if( PLATFORM==PLATFORM_WINDOWS )
	_aligned_free(Ptr);
#else
#error Need define align alloc function
#endif
}

void* Realloc( void* orgbuf, size_t size )
{
	Free(orgbuf);
	return Malloc(size);
}


__END_NAMESPACE
